﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace GodPl.GameObjects.Creatures.Actions
{
    public class AMoveTowards : BriyyaAction
    {

        static readonly TimeSpan minDuration = new TimeSpan(0, 0, 1);
        static readonly TimeSpan maxDuration = new TimeSpan(0, 0, 15);

        public static readonly float GroundDragFactor = 0.58f;
        public static readonly float RepelFactor = -1000f;
        public static readonly float AttractFactor = 0.5f;
        public static readonly float MaxSpeed = 20f; // Pixels per second


        IObstacle iobsTarget;
        IObstacle randomObstacle = null;

        public AMoveTowards(Briyya actor, GameObject target) : base (actor, target)
        {
            assertTarget();
        }


        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            if (!this.Running)
            {
                return;
            }

            iobsTarget = (IObstacle)target;

            if (actor == target ||
                actor.DistanceTo(target) <= target.BoundingRectangle.DiagonalLength() / 2 ||
                actor.BoundingRectangle.GetIntersectionDepth(target.BoundingRectangle) != Vector2.Zero)
            {
                actor.Velocity = Vector2.Zero;
                finished = true;
                return;
            }

            float elapsedSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds;
            Vector2 attractForce = iobsTarget.GetForce(actor, AttractFactor, true);
            Vector2 repelForce = Vector2.Zero;

            var obstacles = from o in actor.World.GameObjects
                            where ((o as IObstacle != null) &&
                                   o != actor && o != target)
                            select o;

            foreach (IObstacle o in obstacles)
            {
                repelForce += o.GetForce(actor, RepelFactor, false);
            }


            TimeSpan joltTime = elapsed - (new TimeSpan(maxDuration.Ticks / 2));

            if (joltTime > (new TimeSpan()) && actor.Velocity.Length() < actor.MaxSpeed / 10)
            {
                if (randomObstacle == null)
                {
                    randomObstacle = (IObstacle)obstacles.ElementAt(GodPlGame.RandomGen.Next(0, obstacles.Count()));
                }
                repelForce += randomObstacle.GetForce(actor, RepelFactor, false) * 8;
            }

            Vector2 netForce = attractForce + repelForce;

            actor.Velocity += netForce * GroundDragFactor * actor.MaxSpeed * elapsedSeconds;

            Vector2 finalHeading = target.Position - actor.Position;

            actor.Rotation = (float)(Math.Atan2(finalHeading.Y, finalHeading.X) + Math.PI / 2);
        }


        public override void  Finish()
        {
            actor.Velocity = Vector2.Zero;
 	        base.Finish();
        }


        public override bool Interrupt()
        {
            actor.Velocity = Vector2.Zero;
            return base.Interrupt();
        }

        protected override TimeSpan MinDuration
        {
            get { return minDuration; }
        }

        protected override TimeSpan MaxDuration
        {
            get { return maxDuration; }
        }
    }
}
